import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ChatListItem } from '../entity/chat.entity';
import { ChatDetailPage } from '../chat-detail/chat-detail';

import 'reflect-metadata';

declare let cordova: any;

@Component({
  selector: 'page-chat-list',
  templateUrl: 'chat-list.html'
})
export class ChatListPage {

  private actionRepository: { [key: string]: ActionHolder } = {};

  public chatList: ChatListItem[] = [new ChatListItem('Chat-first', 'This is subTitle')];

  /************ Life Cycle ************/
  constructor(
    public navCtrl: NavController
  ) {

    this.bindActions();

    const regX = new RegExp(
      `(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})` +
      `\/(((0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)` +
      `\/(0[1-9]|[12][0-9]|30))|(02\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))` +
      `\/02\/29)`
    )
    console.log('正则: ' + regX.test('2008/02/29'));
  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad ChatListPage');
  }

  /************ Public Actions ************/
  onItemClicked(item: ChatListItem) {
    console.log('---show chat detail---');
    
    this.navCtrl.push(ChatDetailPage);

    // this.dispatch('xxxxxx');
    // const modal = this.modalCtrl.create(ChatDetailPage);
    // modal.present();
  }

  onShowDatePickerAction() {
    const options = {
      type: 'date',
      defaultSelectedIndex: [0, 0, 0],
      buttonContainerHeight: 120,
      pickerContainerHeight: 464,
      buttonStyle: { height: 88, width: 160, marginRight: 32, text: '送信', fontSize: 24 },
      datas: [],
      rowHeight: 84.0,
      componentWidth: [598, 320, 320],
      lineStyle: { height: 4, color: '40b9ae' },
      textfontStyle: { fontSize: 48, alignment: 'left' },
      labelText: ['年', '月', '日'],
      labelStyle: { fontSize: 32, width: 80 }
    };

    // cordova.plugins.dhdtPluginPicker.show(options, (val) => {
      
    // });
  }

  /************ Private Functions ************/
  // 1.绑定
  private bindActions() {
    // tslint:disable-next-line:
    for (const methodName in this) {
      const decorator = Reflect.getMetadata('actionBind', this, methodName);
      if (decorator == null) {
        continue;
      }
      
      // 直接执行
      // this[methodName].apply(this, ['qqqqqqqq']);

      // dispatch时执行
      this.register(decorator.actionType, this, methodName);
    }
  }

  // 2.注册
  public register(actionType: string, target: any, methodName: string) {
    const actionHolder = this.actionRepository[actionType] || new ActionHolder();
    // const actionHolder = this.actionRepository[actionType] || new ActionHolder(actionType);
    actionHolder.add(target, methodName);
    this.actionRepository[actionType] = actionHolder;
  }

  // 3.执行
  public dispatch(payload: any) {
    const actionHolder = this.actionRepository['test_A'];
    if (actionHolder == null) {
      return;
    }
    actionHolder.invoke(payload);
  }

  @ActionBind('test_A')
  private actionBindTest_A(payload) {
    console.log(payload);
    console.log('----------------------------');
  }

  @ActionBind('test_B')
  private actionBindTest_B(payload) {
    console.log(payload);
    console.log('++++++++++++++++++++++++++++');
  }
}

class ActionHolder {
  private stores: Array<{ instance: Object, methodName: string }>;

  private action: { instance: Object, methodName: string };

  constructor() {
    this.stores = [];
  }

  public add(instance: any, methodName: string) {
    // old ->
    // this.stores.forEach((item) => {
    //   if (item.instance === instance) {
    //     return;
    //   }
    // });
    // this.stores.push({ instance, methodName });

    // new ->
    this.action = { instance, methodName };
  }

  public remove(instance: any) {
    this.stores = this.stores.filter((item) => {
      return item.instance !== instance;
    });
  }

  public invoke(payload: any) {
    // old ->
    // this.stores.map((item) =>
    //   // console.log(typeof(item.instance))
    //   item.instance[item.methodName].apply(item.instance, [payload])
    // );
    // this.stores.forEach(item => {
    //   item.instance[item.methodName].apply(item.instance, [payload])
    // });

    // new ->
    const instance = this.action.instance;
    const methodName = this.action.methodName;
    instance[methodName].apply(instance, [payload]);
  }
}

export function ActionBind(actionType: string): any {
  const metadata = Reflect.metadata('actionBind', {
    actionType: actionType
  });
  console.log(metadata);
  return metadata
}

declare global {

  function metadata(metadataKey: any, metadataValue: any): {
    (target: Function): void;
    (target: Object, propertyKey: string | symbol): void;
  }

}
